package com.example.demo.web.rest.util;


import com.google.common.collect.Maps;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cglib.beans.BeanMap;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;


/**
 * 批量导出excel(大数据量)
 *
 * @author linxiao
 */
public class ExcelExportUtil {

    private static Logger logger = LoggerFactory.getLogger(ExcelExportUtil.class);

    /**
     * 获取Row
     * @param rowCounter
     * @param sheet
     * @return
     */
    public static Row getRow(int rowCounter, Sheet sheet) {
        Row row = sheet.getRow(rowCounter);
        if (row == null) {
            row = sheet.createRow(rowCounter);
        }
        return row;
    }


    /**
     * 获取Cell
     * @param row
     * @param column
     * @return
     */
    public static Cell getCell(Row row, int column) {
        Cell cell = row.getCell(column);

        if (cell == null) {
            cell = row.createCell(column);
        }
        return cell;
    }

    /**
     * 创建Cell
     * @param cellIndex
     * @param row
     * @param value
     */
    public static void createCell(int cellIndex, Row row, Object value) {
        Cell cell = getCell(row, cellIndex);
        if (null != value) {
            if ("java.lang.Integer".equals(value.getClass().getName())) {
                cell.setCellValue(Double.parseDouble(value.toString()));
            } else if ("java.lang.Double".equals(value.getClass().getName())) {
                cell.setCellValue(((Double) value).doubleValue());
            } else if ("java.util.Date".equals(value.getClass().getName())) {
                cell.setCellValue((Date) value);
            } else if ("java.lang.Boolean".equals(value.getClass().getName())) {
                cell.setCellValue(((Boolean) value).booleanValue());
            } else {
                cell.setCellValue(value.toString());
            }
        } else {
            cell.setCellValue("");
        }
    }

    /**
     * 导入非空判断
     * */
    public static String getCellValue(Cell cell){
        DateFormat formater = new SimpleDateFormat("yyyy-MM-dd");
        String value = "";
        if(cell == null || cell.equals("")){
            return value;
        }
        if (0 == cell.getCellType()) {
            //判断是否为日期类型
            if(HSSFDateUtil.isCellDateFormatted(cell)){
                //用于转化为日期格式
                Date d = cell.getDateCellValue();
                value = formater.format(d);
            }else{
                Boolean a = isIntegerForDouble(cell.getNumericCellValue());
                if(a){
                    // 用于格式化数字，只保留数字的整数部分
                    DecimalFormat df = new DecimalFormat("########");
                    value = df.format(cell.getNumericCellValue());
                }else{
                    value = String.valueOf(cell.getNumericCellValue());
                }
            }
        }else{
            cell.setCellType(Cell.CELL_TYPE_STRING);
            value =cell.getStringCellValue();
        }
        return value;
    }

    /**
     * 判断double是否是整数
     * @param obj
     * @return
     */
    public static boolean isIntegerForDouble(double obj) {
        double eps = 1e-10;  // 精度范围
        return obj-Math.floor(obj) < eps;
    }

    /**
     * 创建Cell
     * @param cellIndex
     * @param row
     * @param value
     */
    public static void createCellWithSty(int cellIndex, Row row, Object value, CellStyle cellStyle) {
        Cell cell = getCell(row, cellIndex);
        if (cellStyle !=null) {
            cell.setCellStyle(cellStyle);
        }
        if (null != value) {
            if ("java.lang.Integer".equals(value.getClass().getName())) {
                cell.setCellValue(Double.parseDouble(value.toString()));
            } else if ("java.lang.Double".equals(value.getClass().getName())) {
                cell.setCellValue(((Double) value).doubleValue());
            } else if ("java.util.Date".equals(value.getClass().getName())) {
                cell.setCellValue((Date) value);
            } else if ("java.lang.Boolean".equals(value.getClass().getName())) {
                cell.setCellValue(((Boolean) value).booleanValue());
            } else {
                cell.setCellValue(value.toString());
            }
        } else {
            cell.setCellValue("");
        }
    }

    /**
     * 将对象装换为map
     * @param bean
     * @return
     */
    public static <T> Map<String, Object> beanToMap(T bean) {
        Map<String, Object> map = Maps.newHashMap();
        if (bean != null) {
            BeanMap beanMap = BeanMap.create(bean);
            for (Object key : beanMap.keySet()) {
                map.put(key + "", beanMap.get(key));
            }
        }
        return map;
    }


    // 下载文件
    public static void download(HttpServletRequest request, HttpServletResponse response, File file, String realName)
        throws Exception {
        String contentType = "application/octet-stream";
        response.setContentType("text/html;charset=UTF-8");
        request.setCharacterEncoding("UTF-8");
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;
        long fileLength = file.length();
        response.setContentType(contentType);
        response.setHeader("Content-disposition",
            "attachment; filename=" + new String(realName.getBytes("utf-8"), "ISO8859-1"));
        response.setHeader("Content-Length", String.valueOf(fileLength));

        bis = new BufferedInputStream(new FileInputStream(file));
        bos = new BufferedOutputStream(response.getOutputStream());
        byte[] buff = new byte[2048];
        int bytesRead;
        while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
            /*String bufferStr = ESAPI.encoder().encodeForBase64(buff,false);
            buff = ESAPI.encoder().decodeFromBase64(bufferStr);*/
            bos.write(buff, 0, bytesRead);
        }
        bis.close();
        bos.close();
    }

    /**
     * 导出文件
     * @param request
     * @param response
     * @param strEname
     * @param strCname
     * @param exportFileName
     * @param showList
     */
    /*public static void exportData(HttpServletRequest request, HttpServletResponse response, String[] strEname, String[] strCname, String exportFileName, String sheetName, List showList) {
        ServletOutputStream sos = null;
        try{
            // 声明一个工作薄
            SXSSFWorkbook book = new SXSSFWorkbook();
            // 生成一个表格
            Sheet sheet = book.createSheet(sheetName);
            //表头
            Row titleRow = getRow(0, sheet);
            for (int i = 0; i < strCname.length; ++i) {
                ExcelExportUtil.createCell(i, titleRow, strCname[i]);
            }
            //插入需导出的数据
            int writeRowNum = 1;
            for(int i = 0;i<showList.size();i++){
                // 新建行
                Row writeRow = ExcelExportUtil.getRow(writeRowNum, sheet);
                Map<String, Object> ipMap = ExcelExportUtil.beanToMap(showList.get(i));
                for (int j = 0; j < strEname.length; j++) {
                    ExcelExportUtil.createCell(j, writeRow, ipMap.get(strEname[j]));
                }
                writeRowNum++;
            }
            String contentType = "application/octet-stream";
            request.setCharacterEncoding(StandardCharsets.UTF_8.displayName());
            response.setContentType(contentType);
            response.setHeader("Content-disposition", "attachment; filename=" + new String(exportFileName.getBytes("utf-8"), "ISO8859-1"));
            sos = response.getOutputStream();
            book.write(sos);
        }catch (Exception e) {
            e.printStackTrace();
        }finally {
            if(sos!=null){
                try {
                    sos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }*/
}

